home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / sonido / mod-0.000 / mod-0 / mod / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-29  |  6.2 KB  |  264 lines

  1. /*
  2.  *  main.c - Initialization before main-loop and cleanup before exit.
  3.  *
  4.  *  (C) 1994 Mikael Nordqvist (d91mn@efd.lth.se, mech@df.lth.se)
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9. #include <unistd.h>
  10. #include <stdlib.h>
  11. #include <fcntl.h>
  12. #include <sys/wait.h>
  13. #include <errno.h>
  14. #include <sys/soundcard.h>
  15. #include <sys/stat.h>
  16. #include <dirent.h>
  17. #include <termios.h>
  18. #include <signal.h>
  19. #include <string.h>
  20. #include <time.h>
  21.  
  22. #include "mod.h"
  23.  
  24. SEQ_DECLAREBUF();
  25. extern int seqfd, gus_dev;
  26. extern struct options default_opt;
  27. extern char quit;
  28.  
  29. int total_time;
  30.  
  31. struct mod_info M;         /* The module */
  32. char workdir[PATH_MAX+1];  /* The directory mod was started from */
  33. int ack_pipe[2];           /* Player sends acks to main through this one */
  34. int player2main_synced[2]; /* Message from player to main (synced) */
  35. int main2player[2];        /* Message from main to player */
  36.  
  37. pid_t pid_main, pid_player;
  38.  
  39. int main(int argc, char *argv[])
  40. {
  41.     struct termios tio, orig_tio;
  42.     char tmp, day, hour, min, sec;
  43.  
  44.     srand(time((time_t)0));    /* Randomize */
  45.     getcwd(workdir, PATH_MAX); /* Store working directory */
  46.  
  47.     if(!strcmp("mod_mklist", argv[0]))
  48.     mklist(argc, argv);    /* Must be after workdir is set */
  49.     
  50.     if(mkdir(TMP_DIR , 0777) && errno != EEXIST)
  51.     error("Unable to create " TMP_DIR ".\n");
  52.     
  53.     chmod(TMP_DIR, 0777); /* This is needed as mode&umask is used in mkdir */
  54.     
  55.     if(argc >= 2 && !strncmp(argv[1], "-k", 2))
  56.     kill_mod();
  57.  
  58.     /* Special case to allow help if mod is already running */
  59.     if(argc >= 2 && !strncmp(argv[1], "-h", 2)) {
  60.     print_helptext(argv[0]);
  61.     exit(0);
  62.     }
  63.     
  64.     init_sound(); /* Make sure audio-resources are available and grab them */
  65.     init_options(argc, argv);
  66.     
  67.     pid_main=getpid();
  68.     
  69.     /* Create communication-pipes */
  70.     if(pipe(player2main_synced) || pipe(main2player) || pipe(ack_pipe))
  71.         error("Unable to create pipes.");
  72.  
  73.     /* Player should never block */
  74.     fcntl(player2main_synced[PIPE_WRITE], F_SETFL, O_NONBLOCK);
  75.  
  76.     /* Set up terminal if verbose (turn off linebuffering and echo) */
  77.     if(default_opt.verbose) {
  78.     tcgetattr(STDIN_FILENO, &orig_tio);
  79.     tio=orig_tio;
  80.     tio.c_lflag&=~(ICANON|ECHO);
  81.     tio.c_cc[VMIN]=1;
  82.     tio.c_cc[VTIME]=0;
  83.     tcsetattr(STDIN_FILENO, TCSADRAIN, &tio);
  84.     }
  85.     fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); /* Never block on keyboard */
  86.   
  87.     if(default_opt.interactive) {
  88.     init_screen(); /* This one changes signal-handlers ! */
  89.     }
  90.  
  91.     /* Install signal handlers _after_ ncurses initscr() */
  92.     pid_player=1;        /* Make sure handlers know we are the main process */
  93.     install_signalhandlers();
  94.  
  95.     cleanup_sound();  /* Free resources before entering main loop */
  96.     zero_resources(); /* Make sure nothing undefined get free()'d */
  97.     total_time=0;
  98.  
  99.     main_loop();      /* Do it! */
  100.  
  101.     /* Clean up */
  102.     cleanup_options();
  103.     
  104.     if(default_opt.verbose)
  105.     tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_tio);
  106.     
  107.     if(default_opt.interactive)
  108.     cleanup_screen();
  109.  
  110.     info("\n");
  111.  
  112.     chdir(TMP_DIR);
  113.     chdir("..");
  114.     my_removedir(TMP_DIR);  /* Try to delete all garbage-files in TMP_DIR */
  115.     
  116.     if(!default_opt.quiet && total_time && quit != QUIT_SIGNAL) {
  117.     day=total_time/(24*3600);
  118.     hour=(total_time/3600)%24;
  119.     min=(total_time/60)%60;
  120.     sec=total_time%60;
  121.  
  122.     printf("Total time spent playing was ");
  123.     tmp=0;
  124.     if(day) {
  125.         if(day == 1)
  126.         printf("1 day, ");
  127.         else
  128.         printf("%d days, ", day);
  129.         tmp=1;
  130.     }
  131.     if(tmp || hour) {    
  132.         if(hour == 1)
  133.         printf("1 hour, ");
  134.         else
  135.         printf("%d hours, ", hour);
  136.         tmp=1;
  137.     }
  138.     if(tmp || min) {
  139.         if(min == 1)
  140.         printf("1 minute and ");
  141.         else
  142.         printf("%d minutes and ", min);
  143.         tmp=1;
  144.     }
  145.     if(sec == 1)
  146.         printf("1 second.\n");
  147.     else
  148.         printf("%d seconds.\n", sec);
  149.     }
  150.     return 0;
  151. }
  152.  
  153. /* Removes a directory (recursively) located in the _current directory_ */
  154.  
  155. void my_removedir(char *name)
  156. {
  157.     DIR *d;
  158.     struct dirent *de;
  159.     struct stat s;
  160.  
  161.     if(!chdir(name)) {
  162.     if((d=opendir("."))) {
  163.         while((de=readdir(d))) {
  164.         if(strcmp(de->d_name, ".") && strcmp(de->d_name, "..") &&
  165.            strcmp(de->d_name, "mod.pid")) {
  166.             if(stat(de->d_name, &s))
  167.             continue;
  168.             chmod(de->d_name, 0777); /* a+rwx */
  169.             if(S_ISDIR(s.st_mode)) {
  170.             my_removedir(de->d_name);
  171.             }
  172.             else
  173.             unlink(de->d_name);
  174.         }
  175.         }
  176.         chmod("mod.pid", 0777); /* a+rwx */
  177.         unlink("mod.pid"); /* Remove this one last if it exists.
  178.                 * Can't remember WHY I wait with that one...
  179.                 */
  180.         closedir(d);        
  181.     }
  182.     chdir("..");
  183.     }
  184.     rmdir(name); /* May or may not work depending on owner of dir */
  185. }
  186.  
  187. void write_pid(pid_t p)
  188. {
  189.     int fd;
  190.     char buf[10];
  191.  
  192.     if((fd=open(TMP_DIR"/mod.pid", O_RDONLY)) != -1) {
  193.     error("There is a copy of mod running in the background, try mod -k.\n");
  194.     }
  195.  
  196.     if((fd=open(TMP_DIR"/mod.pid", O_CREAT|O_TRUNC|O_WRONLY, 0777)) == -1)
  197.     error("Unable to write 'mod.pid'", errno);
  198.     sprintf(buf, "%09d\n", p);
  199.     write(fd, buf, 10);
  200.     close(fd);
  201.     chmod(TMP_DIR"/mod.pid", 0777);
  202. }
  203.  
  204.  
  205. void kill_mod(void)
  206. {
  207.     int fd, p;
  208.     char buf[10];
  209.  
  210.     if((fd=open(TMP_DIR"/mod.pid", O_RDONLY)) == -1)
  211.     error("No copy of mod running in the background.\n");
  212.  
  213.     if(read(fd, buf, 12) != 10)
  214.     error("Trouble reading 'mod.pid'.\n");
  215.     close(fd);
  216.     p=atoi(buf);
  217.     if(kill(p, SIGTERM)) {
  218.     if(errno == EPERM)
  219.         error("You don't have permission to kill the running copy of"
  220.           " 'mod'.\n");
  221.     else if(errno == ESRCH) {
  222.         if(!unlink(TMP_DIR"/mod.pid")) {
  223.         printf("Stale lock removed.\n");
  224.         exit(0);
  225.         }
  226.         else
  227.         error("Unable to remove stale lock.");
  228.     }
  229.     else
  230.         error("No copy of mod running in the background.\n");
  231.     }
  232.     printf("Killed.\n");
  233.     exit(0);
  234. }
  235.  
  236.  
  237. /* Main-process:  Set quit-flag, kill child.
  238.  * Child-process: Terminate. Maybe we should kill() father also?
  239.  */
  240.  
  241. void handler_quit(int sig)
  242. {
  243.     if(pid_player) {
  244.     signal(sig, handler_quit);
  245.     if(pid_player != 1) /* Before forking of the first child */
  246.         kill(pid_player, sig);
  247.     quit=QUIT_SIGNAL;
  248.     }
  249.     else {
  250.     cleanup_sound();
  251.     exit(0);
  252.     }
  253. }
  254.  
  255.  
  256. void install_signalhandlers(void)
  257. {
  258.     signal(SIGHUP, handler_quit);
  259.     signal(SIGINT, handler_quit);
  260.     signal(SIGQUIT, handler_quit);
  261.     signal(SIGTERM, handler_quit);
  262.     signal(SIGTSTP, SIG_IGN);     /* Maybe support suspension ? */
  263. }
  264.